# -*- coding: utf-8 -*-

from flask import Blueprint, g, session, request, abort, redirect, url_for
from google.appengine.api import users
from google.appengine.ext import db

from dicthash.utils import Bunch
from dicthash.decorators import anonymous_required_decor_factory, login_required_decor_factory

from . import config

auth_blueprint = Blueprint('auth', __name__)

def create_login_url(dest):
    """ """
    return users.create_login_url(url_for('auth.start_login') + '?next=' + dest)

def create_logout_url(dest):
    """ """
    return url_for('auth.logout') + '?next=' + dest

anonymous_required = anonymous_required_decor_factory(
    lambda: g.user, 
    lambda: abort(403, 'You are already logged in.')
)

login_required = login_required_decor_factory(
    lambda: g.user,
    lambda: create_login_url('/')
)


def register(app, url_prefix, options, prototype=False):
    """
    `config.USER_NAME_VALIDATOR`: returns tuple (name, error).
    If validation fails then returns (None, error), otherwise (name, None).
    """
    config.User = options['user_class']
    config.UserExceptions = options.get('user_exceptions') or config.UserExceptions
    config.DEFAULT_DESTINATION = options['default_destination']
    config.SESSION_KEY_NAME = options.get('session_key_name') or config.SESSION_KEY_NAME
    config.USER_NAME_VALIDATOR = options['user_name_validator']
    
    if prototype:
        from . import prototype_views as views
    else:
        from . import views
            
    auth_blueprint.add_url_rule('/start',
        'start_login',
        anonymous_required(views.login_handler),
        methods=['GET']
    )
    
    auth_blueprint.add_url_rule('/create',
        'create_app_user', 
        anonymous_required(views.create_user_handler),
        methods=['POST']
    )
    
    auth_blueprint.add_url_rule('/logout',
        'logout', 
        views.logout_handler,
        methods=['GET']
    )
    
    app.register_blueprint(auth_blueprint, url_prefix=url_prefix)
    

class GoogleUserWrapper():
    """ """
    def __init__(self, google_user):
        self.google_user = google_user
    
    @property    
    def openid(self):
        return self.google_user.federated_identity() or self.google_user.email()    

def get_current_user():
    """ """
    google_user = users.get_current_user()
    return GoogleUserWrapper(google_user) if google_user else None


def set_user():
    """ Before request """
    g.google_user = google_user = get_current_user()
    g.user = None
    _set_user(google_user)

def _set_user(google_user):
    """ """
    SESSION_KEY_NAME = config.SESSION_KEY_NAME
    
    if google_user:
        if SESSION_KEY_NAME in session:
            sd = session[SESSION_KEY_NAME]
            try:
                user = Bunch(name=sd['name'], openid=sd['openid'])
            except KeyError:
                session.pop(SESSION_KEY_NAME, None)
            else:
                if user.openid == google_user.openid:
                    g.user = user
                else:
                    session.pop(SESSION_KEY_NAME, None)
    else:
        session.pop(SESSION_KEY_NAME, None)
